package com.qls.mt.biz.data.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qls.core.constant.Constant;
import com.qls.core.dto.HtDailyRoom;
import com.qls.core.dto.PushRatesBody;
import com.qls.core.dto.PushRpBody;
import com.qls.core.entity.HtHotel;
import com.qls.core.entity.HtSellRoom;
import com.qls.core.utils.DateUtils;
import com.qls.mt.biz.common.service.HtLogicRoomService;
import com.qls.mt.biz.data.pojo.BreakfastCal;
import com.qls.mt.biz.data.pojo.rp.BookRules;
import com.qls.mt.biz.data.service.CallBackService;
import com.qls.rabbitmq.SendMsg;
import com.qls.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * @author yunchao
 */
@Slf4j
@Service
public class CallBackServiceImpl implements CallBackService {

    /**
     * 过滤缓存h
     */

    @Autowired
    private SendMsg sendMsg;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private HtLogicRoomService htLogicRoomService;


    /**
     * 房态回调
     *
     * @param jsonObject
     */
    @Override
    public void rs(JSONObject jsonObject) {
        JSONObject callback = jsonObject.getJSONObject("data");
        JSONArray rsList = callback.getJSONArray("rsList");
        Integer partnerId = jsonObject.getInteger("partnerId");
        if (Objects.isNull(partnerId)) {
            return;
        }
        for (Object rs : rsList) {
            JSONObject jsonRs = (JSONObject) JSONObject.toJSON(rs);
            Long rpCode = jsonRs.getLong("goodsId");
            boolean flag = this.filter(rpCode, partnerId);
            if (!flag) {
                continue;
            }
            List<HtDailyRoom> htDailyrooms = new ArrayList<>();
            JSONArray goodsStatus = jsonRs.getJSONArray("goodsStatuses");
            for (Object goodsState : goodsStatus) {
                JSONObject goodsStateJson = (JSONObject) JSONObject.toJSON(goodsState);
                String strDate = goodsStateJson.getString("date");
                HtDailyRoom htDailyroom = new HtDailyRoom();
                Integer status = goodsStateJson.getInteger("status");
                // 默认库存为零
                int num = 0;
                if (status == 1) {
                    num = 3;
                }
                htDailyroom.setSaleNum(num);
                htDailyroom.setRpCode(rpCode.toString());
                htDailyroom.setDate(strDate);
                htDailyroom.setStatus(status);
                htDailyrooms.add(htDailyroom);
            }
            redisUtil.saveOrUpdateBatchRates(htDailyrooms);
            // 构造30天日期
            List<String> dates = new ArrayList<>();
            for (int i = 0; i < 30; i++) {
                dates.add(DateUtils.format(DateUtils.addDateDays(new Date(), i)));
            }
            PushRatesBody pushRatesBody = new PushRatesBody();
            pushRatesBody.setHtDailyRooms(redisUtil.getRatesBatch(dates, rpCode.toString()));
            pushRatesBody.setRpCode(rpCode);
            sendMsg.execute(Constant.RabbitMq.CALLBACK_RATES, 1, pushRatesBody);
        }
    }

    @Override
    public void rp(JSONObject jsonObject) {
        JSONObject callback = jsonObject.getJSONObject("data");
        List goodsList = callback.getJSONArray("goods");
        Integer partnerId = jsonObject.getInteger("partnerId");
        Long rpCode;
        List<HtSellRoom> htLogicRooms = new ArrayList<>();
        for (Object goods : goodsList) {
            JSONObject jsonRp = (JSONObject) JSONObject.toJSON(goods);
            rpCode = jsonRp.getLong("goodsId");
            // 价格
            List priceModels = jsonRp.getJSONArray("priceModels");
            //判断该酒店是否推送过
            boolean flag = this.filter(rpCode, partnerId);
            if (!flag) {
                continue;
            }
            htLogicRooms.add(this.htLogicRoom(jsonRp));
            List<HtDailyRoom> htDailyrooms = new ArrayList<>();
            assert priceModels != null;
            for (Object priceModel : priceModels) {
                JSONObject jsonPriceModel = (JSONObject) JSONObject.toJSON(priceModel);
                String strDate = jsonPriceModel.getString("date");
                Integer price = jsonPriceModel.getInteger("salePrice");
                Integer subPrice = jsonPriceModel.getInteger("subPrice");
                HtDailyRoom htDailyroom = new HtDailyRoom();
                htDailyroom.setRpCode(rpCode.toString());
                htDailyroom.setDate(strDate);
                htDailyroom.setPrice(price);
                htDailyroom.setSubPrice(subPrice);
                htDailyrooms.add(htDailyroom);
            }
            redisUtil.saveOrUpdateBatchRates(htDailyrooms);
            // 构造30天日期
            List<String> dates = new ArrayList<>();
            for (int i = 0; i < 30; i++) {
                dates.add(DateUtils.format(DateUtils.addDateDays(new Date(), i)));
            }
            PushRatesBody pushRatesBody = new PushRatesBody();
            pushRatesBody.setHtDailyRooms(redisUtil.getRatesBatch(dates, rpCode.toString()));
            pushRatesBody.setRpCode(rpCode);
            sendMsg.execute(Constant.RabbitMq.CALLBACK_RATES, 1, pushRatesBody);
        }
        if (!htLogicRooms.isEmpty()) {
            List<Long> ids = new ArrayList<>();
            for (HtSellRoom htSellRoom : htLogicRooms) {
                ids.add(htSellRoom.getRpCode());
            }
            List<HtSellRoom> htSellRooms = htLogicRoomService.listByIds(ids);
            List<HtSellRoom> newHtSellRoom = new ArrayList<>();
            for (HtSellRoom htSellRoom : htLogicRooms) {
                for (HtSellRoom htSellRoom1 : htSellRooms) {
                    if (htSellRoom.getRpCode().equals(htSellRoom1.getRpCode())) {
                        if (!htSellRoom.getBreakfastNum().equals(htSellRoom1.getBreakfastNum())) {
                            newHtSellRoom.add(htSellRoom);
                            break;
                        }
                        if (!htSellRoom.getMaxHours().equals(htSellRoom1.getMaxHours())) {
                            newHtSellRoom.add(htSellRoom);
                            break;
                        }
                        if (!htSellRoom.getMinHours().equals(htSellRoom1.getMinHours())) {
                            newHtSellRoom.add(htSellRoom);
                            break;
                        }
                        if (!htSellRoom.getCancelPolicy().equals(htSellRoom1.getCancelPolicy())) {
                            newHtSellRoom.add(htSellRoom);
                            break;
                        }
                        if (!htSellRoom.getMaxDays().equals(htSellRoom1.getMaxDays())) {
                            newHtSellRoom.add(htSellRoom);
                            break;
                        }
                        if (!htSellRoom.getMinDays().equals(htSellRoom1.getMinDays())) {
                            newHtSellRoom.add(htSellRoom);
                            break;
                        }

                    }
                }
            }
            if (!newHtSellRoom.isEmpty()) {
                log.info("售卖房型发生变化：{}", JSONObject.toJSON(newHtSellRoom));
            }
            htLogicRoomService.updateBatchById(newHtSellRoom);
            for (HtSellRoom htSellRoom : newHtSellRoom) {
                PushRpBody pushRpBody = new PushRpBody();
                pushRpBody.setRpCode(htSellRoom.getRpCode());
                pushRpBody.setPartnerId(partnerId);
                pushRpBody.setType(1);
                sendMsg.execute(Constant.RabbitMq.CALLBACK_RP, 1, pushRpBody);
            }
        }
    }

    @Override
    public void poi(JSONObject jsonObject) {
        JSONObject callback = jsonObject.getJSONObject("data");
        Integer partnerId = jsonObject.getInteger("partnerId");
        List hotelList = callback.getJSONArray("hotelList");
        for (Object hotel : hotelList) {
            int status = 0;
            JSONObject jsonHotel = (JSONObject) JSONObject.toJSON(hotel);
            Long hotelCode = jsonHotel.getLong("hotelId");
            Integer type = jsonHotel.getInteger("type");
            HtHotel htHotelinfo = new HtHotel();
            if (type == 2) {
                status = -2;
            }
            htHotelinfo.setId(hotelCode);
            htHotelinfo.setHotelStatus(status);
            htHotelinfo.setPartnerId(partnerId);
            sendMsg.execute(Constant.RabbitMq.CALLBACK_HOTEL, 1, htHotelinfo);
        }

    }


    /**
     * rp组装
     *
     * @param jsonRp
     * @return
     */
    private HtSellRoom htLogicRoom(JSONObject jsonRp) {
        HtSellRoom htLogicRoom = new HtSellRoom();
        Long hotelCode = jsonRp.getLong("hotelId");
        Long rpCode = jsonRp.getLong("goodsId");
        // 早餐list
        Object breakfastList = jsonRp.get("breakfast");
        //房型信息
        Object cancelRules = jsonRp.getJSONArray("cancelRules");
        htLogicRoom.setRpCode(rpCode);
        htLogicRoom.setId(rpCode);
        //产品名称
        String goodsName = jsonRp.getString("goodsName");
        if (Objects.isNull(goodsName)) {
            goodsName = "全额预付";
        } else {
            String regEx = "\\(.*\\)|\\[.*\\]|\\（.*\\）";
            goodsName = goodsName.replaceAll(regEx, "");
        }
        htLogicRoom.setRpName(goodsName);
        // 取消规则list
        JSONArray jsonArray = jsonRp.getJSONArray("bookRules");
        List<BookRules> bookRulesList = JSONObject.parseArray(jsonArray.toJSONString(), BookRules.class);
        //预订政策-------------------------------------------------
        Map<String, Object> bookRuleMap = bookRule(bookRulesList);
        Integer minDay = Integer.parseInt(bookRuleMap.get("minDays").toString());
        Integer maxDay = Integer.parseInt(bookRuleMap.get("maxDays").toString());
        Integer minBookHour = Integer.parseInt(bookRuleMap.get("minBookHours").toString());
        Integer maxBookHour = Integer.parseInt(bookRuleMap.get("maxBookHours").toString());
        //连续入住最少天数，0表示不限制
        htLogicRoom.setMinDays(minDay);
        //	连续入住最多天数，0表示不限制
        htLogicRoom.setMaxDays(maxDay);
        //最早预订时间，格式为HH:mm:ss, 空值表示不限制。
        htLogicRoom.setMinHours(minBookHour);
        //最晚预订时间，格式为HH:mm:ss, 空值表示不限制
        htLogicRoom.setMaxHours(maxBookHour);

        // 早餐取消政策
        if (breakfastList != null) {
            List bfList = (List) breakfastList;
            for (Object breakfast : bfList) {
                // 某天的早餐规则
                List<BreakfastCal> breakfastCals = new ArrayList<>();
                JSONObject breakfastJson = (JSONObject) JSONObject.toJSON(breakfast);

                int breakfastNum = 0;
                int breakfastType = breakfastJson.getInteger("breakfastType");
                if (breakfastType == 1) {
                    breakfastNum = breakfastJson.getInteger("breakfastNum");
                }
                int inStartDate = breakfastJson.getInteger("inStartDate");
                int inEndDate = breakfastJson.getInteger("inEndDate");
                if (inStartDate == 0 & inEndDate == 0) {
                    htLogicRoom.setBreakfastNum(breakfastNum);
                } else {
                    BreakfastCal breakfastCal = new BreakfastCal();
                    String startDate = DateUtils.intDate2String(inStartDate);
                    String endDate = DateUtils.intDate2String(inEndDate);
                    breakfastCal.setBreakfast_count(breakfastNum);
                    breakfastCal.setDate(null);
                    breakfastCal.setStartDate(startDate);
                    breakfastCal.setEndDate(endDate);
                    breakfastCals.add(breakfastCal);
                }
                if (!breakfastCals.isEmpty()) {
                    htLogicRoom.setBreakfastCal(breakfastCals.toString());
                }
            }
        }

        // 早餐规则
        if (breakfastList != null) {
            List bfList = (List) breakfastList;
            for (Object breakfast : bfList) {
                JSONObject breakfastJson = (JSONObject) JSONObject.toJSON(breakfast);
                int breakfastNum = 0;
                int breakfastType = breakfastJson.getInteger("breakfastType");
                if (breakfastType == 1) {
                    breakfastNum = breakfastJson.getInteger("breakfastNum");
                }
                htLogicRoom.setBreakfastNum(breakfastNum);
            }
        }

        // 取消规则
        if (cancelRules != null) {
            List calcelList = (List) cancelRules;
            JSONObject cancelRule = new JSONObject();
            JSONObject cancelRuleJson = (JSONObject) calcelList.get(0);
            int cancelType = cancelRuleJson.getInteger("cancelType");
            if (cancelType == 0) {
                cancelRule.put("cancelPolicyType", 2);
            } else {
                cancelRule.put("cancelPolicyType", 5);
                JSONObject policyInfo = new JSONObject();
                // 可取消
                int aheadCancelDays = cancelRuleJson.getInteger("aheadCancelDays");
                int aheadHour = aheadCancelDays * 24;
                // 总时间量
                int allHour;
                int deductType = cancelRuleJson.getInteger("deductType");
                if (deductType == 0) {
                    // 提前取消时间
                    String aheadCancelHours = cancelRuleJson.getString("aheadCancelHours");
                    int hour = DateUtils.time2Hour(aheadCancelHours);
                    allHour = aheadHour + hour;
                    if (allHour <= 0) {
                        allHour = 1;
                    }
                    policyInfo.put("timeBefore", allHour);
                } else {
                    // 提前取消时间量
                    int aheadCancelHours = cancelRuleJson.getInteger("aheadCancelHours");
                    allHour = aheadHour + aheadCancelHours;
                    if (allHour <= 0) {
                        allHour = 1;
                    }
                    policyInfo.put("timeBefore", allHour);
                }
                cancelRule.put("policyInfo", policyInfo);
            }
            htLogicRoom.setCancelPolicy(cancelRule.toJSONString());
        }
        // 价格计划状态
        int status = 1;
        if (jsonRp.getInteger("goodsStatus") != status) {
            status = 2;
        }
        htLogicRoom.setRpStatus(status);
        return htLogicRoom;
    }

    /**
     * 预定政策
     *
     * @param bookRulesList
     * @return
     */
    private Map<String, Object> bookRule(List<BookRules> bookRulesList) {
        Map<String, Object> map = new HashMap<>();
        int minDays = 1;
        int maxDays = 90;
        int minBookHours = 0;
        int maxBookHours = 720;
        // 为空默认值
        if (bookRulesList != null && !bookRulesList.isEmpty()) {
            for (BookRules bookRules : bookRulesList) {
                Integer start = bookRules.getInStartDate();
                Integer end = bookRules.getInEndDate();
                Date nowDate = new Date();
                Date startDate = DateUtils.addDateDays(nowDate, -1);
                Date endDate = DateUtils.addDateYears(nowDate, 1);
                if (start != 0) {
                    startDate = DateUtils.stringToDate(DateUtils.dateChange(start.toString()), DateUtils.DATE_PATTERN);
                }
                if (end != 0) {
                    endDate = DateUtils.stringToDate(DateUtils.dateChange(end.toString()), DateUtils.DATE_PATTERN);
                }
                assert startDate != null;
                if (DateUtils.isEffectiveDate(nowDate, startDate, endDate)) {
                    Integer bookDaysEarliest = bookRules.getEarliestBookingDays();
                    if (bookDaysEarliest != null && bookDaysEarliest != 0 && bookDaysEarliest != -1) {
                        maxBookHours = 24 * bookDaysEarliest;
                    }
                    String bookHoursEarliest = bookRules.getEarliestBookingHours();
                    if (bookHoursEarliest != null) {
                        maxBookHours += 24 - Integer.parseInt(bookHoursEarliest.substring(0, 2));
                    }
                    Integer bookDaysLatest = bookRules.getLatestBookingDays();
                    if (bookDaysLatest != null && bookDaysLatest != -1 && bookDaysLatest != 0) {
                        minBookHours = 24 * bookDaysLatest;
                    }
                    break;
                }
            }
        }
        map.put("minDays", minDays);
        map.put("maxDays", maxDays);
        map.put("minBookHours", minBookHours);
        map.put("maxBookHours", maxBookHours);
        return map;
    }

    /**
     * 缓存过滤
     *
     * @param rpCode
     * @return
     */
    private boolean filter(Long rpCode, Integer partnerId) {
        Map<String, Object> map = (Map<String, Object>) redisUtil.hashGetObject(Constant.Redis.RP_BL_STORE.getValue(), rpCode.toString());
        if (Objects.isNull(map)) {
            return false;
        }
        List<Integer> storeIds = (List<Integer>) map.get("storeIds");
        if (Objects.isNull(storeIds)) {
            return false;
        }
        Integer partnerIdMap = Integer.valueOf(map.get("partnerId").toString());
        return partnerIdMap.equals(partnerId);
    }


}
